You could use either BUILD or BUILDARGS for this. It's hard to say which would be better without knowing more about what you're trying to do, but I'd guess BUILD would be the better choice.
sub BUILD {
my $self = shift;
my $args = shift;
my $ds = $args->{ds} or confess "Argument (ds) is required";
$self->some_attr($ds->{...});
$self->other_attr($ds->{foo}[3]);
...
} # end BUILD
If you want Moose to check the type and ensure it's present, you have to make it an attribute. But you can clear it in the BUILD method after you use it.
has 'ds' => (
is => 'ro',
isa => 'SomeType',
required => 1,
clearer => '_clear_ds',
);
sub BUILD {
my $self = shift;
my $args = shift;
my $ds = $self->ds;
$self->_clear_ds;
$self->some_attr($ds->{...});
$self->other_attr($ds->{foo}[3]);
...
} # end BUILD
You could name the reader method something else (like _ds) if you wanted to.