diff --git a/altair/vegalite/v2/schema/channels.py b/altair/vegalite/v2/schema/channels.py
index fa9f5b63..dc9a9b4a 100644
--- a/altair/vegalite/v2/schema/channels.py
+++ b/altair/vegalite/v2/schema/channels.py
@@ -24,7 +24,7 @@ class FieldChannelMixin(object):
             # If given a list of shorthands, then transform it to a list of classes
             kwds = self._kwds.copy()
             kwds.pop('shorthand')
-            return [self.__class__(shorthand, **kwds).to_dict()
+            return [self.__class__(shorthand, **kwds).to_dict(validate=validate, ignore=ignore, context=context)
                     for shorthand in self.shorthand]
         elif isinstance(self.shorthand, six.string_types):
             kwds = parse_shorthand(self.shorthand, data=context.get('data', None))
diff --git a/altair/vegalite/v3/schema/channels.py b/altair/vegalite/v3/schema/channels.py
index 871cd468..ba5f5902 100644
--- a/altair/vegalite/v3/schema/channels.py
+++ b/altair/vegalite/v3/schema/channels.py
@@ -24,7 +24,7 @@ class FieldChannelMixin(object):
             # If given a list of shorthands, then transform it to a list of classes
             kwds = self._kwds.copy()
             kwds.pop('shorthand')
-            return [self.__class__(shorthand, **kwds).to_dict()
+            return [self.__class__(shorthand, **kwds).to_dict(validate=validate, ignore=ignore, context=context)
                     for shorthand in self.shorthand]
         elif isinstance(self.shorthand, six.string_types):
             kwds = parse_shorthand(self.shorthand, data=context.get('data', None))
diff --git a/tools/generate_schema_wrapper.py b/tools/generate_schema_wrapper.py
index a9ed8a57..8fe8ba66 100644
--- a/tools/generate_schema_wrapper.py
+++ b/tools/generate_schema_wrapper.py
@@ -88,7 +88,7 @@ class FieldChannelMixin(object):
             # If given a list of shorthands, then transform it to a list of classes
             kwds = self._kwds.copy()
             kwds.pop('shorthand')
-            return [self.__class__(shorthand, **kwds).to_dict()
+            return [self.__class__(shorthand, **kwds).to_dict(validate=validate, ignore=ignore, context=context)
                     for shorthand in self.shorthand]
         elif isinstance(self.shorthand, six.string_types):
             kwds = parse_shorthand(self.shorthand, data=context.get('data', None))

alt.Tooltip not behaving the same way as not specifying the object
Excuse the weird title but I am not sure how to properly phrase the issue. This is on Altair 3.1.

Let's take the following example code from another issue: 

```
from vega_datasets import data
df=data.barley()
base = alt.Chart(df).transform_joinaggregate(
    yield_sum='sum(yield)',
    groupby=['year', 'variety']
).transform_calculate(
    yield_norm='datum.yield / datum.yield_sum'  
).mark_bar().encode(
    x=alt.X('yield', stack='normalize', axis=alt.Axis(title='Normalized Yield', format='.0%')),
    y=alt.Y('variety', title='Variety'),
    tooltip=['yield', 'variety', 'year', 'yield_norm:Q'],
    order='site'
)

bars = base.encode(
    detail='site',
    color=alt.Color('site', title='Site')
)

text = base.mark_text(dx=-15, dy=3).encode(
    text=alt.Text('yield_norm:Q', format='.0%'),
)

alt.layer(bars, text).facet(column=alt.Column('year:O', title='Year'))
```

This works fine. However changing the tooltip line to
`tooltip=alt.Tooltip(['yield', 'variety', 'year', 'yield_norm:Q'])`

will throw the following error:

> ValueError: yield encoding field is specified without a type; the type cannot be automatically inferred because the data is not specified as a pandas.DataFrame.

Should the two ways of specifying the tooltip not work interchangeably? Or is it maybe related to this issue #1573?
diff --git a/altair/vegalite/v3/tests/test_api.py b/altair/vegalite/v3/tests/test_api.py
index a60f282c..3330d106 100644
--- a/altair/vegalite/v3/tests/test_api.py
+++ b/altair/vegalite/v3/tests/test_api.py
@@ -19,6 +19,10 @@ except ImportError:
     selenium = None
 
 
+def getargs(*args, **kwargs):
+    return args, kwargs
+
+
 OP_DICT = {
     'layer': operator.add,
     'hconcat': operator.or_,
@@ -111,28 +115,27 @@ def test_chart_infer_types():
     assert dct['encoding']['y']['type'] == 'ordinal'
 
 
-def test_multiple_encodings():
+@pytest.mark.parametrize('args, kwargs', [
+    getargs(detail=['value:Q', 'name:N'], tooltip=['value:Q', 'name:N']),
+    getargs(detail=['value', 'name'], tooltip=['value', 'name']),
+    getargs(alt.Detail(['value:Q', 'name:N']), alt.Tooltip(['value:Q', 'name:N'])),
+    getargs(alt.Detail(['value', 'name']), alt.Tooltip(['value', 'name'])),
+    getargs([alt.Detail('value:Q'), alt.Detail('name:N')],
+            [alt.Tooltip('value:Q'), alt.Tooltip('name:N')]),
+    getargs([alt.Detail('value'), alt.Detail('name')],
+            [alt.Tooltip('value'), alt.Tooltip('name')]),
+])
+def test_multiple_encodings(args, kwargs):
+    df = pd.DataFrame({
+        'value': [1, 2, 3],
+        'name': ['A', 'B', 'C'],
+    })
     encoding_dct = [{'field': 'value', 'type': 'quantitative'},
                     {'field': 'name', 'type': 'nominal'}]
-    chart1 = alt.Chart('data.csv').mark_point().encode(
-        detail=['value:Q', 'name:N'],
-        tooltip=['value:Q', 'name:N']
-    )
-
-    chart2 = alt.Chart('data.csv').mark_point().encode(
-        alt.Detail(['value:Q', 'name:N']),
-        alt.Tooltip(['value:Q', 'name:N'])
-    )
-
-    chart3 = alt.Chart('data.csv').mark_point().encode(
-        [alt.Detail('value:Q'), alt.Detail('name:N')],
-        [alt.Tooltip('value:Q'), alt.Tooltip('name:N')]
-    )
-
-    for chart in [chart1, chart2, chart3]:
-        dct = chart.to_dict()
-        assert dct['encoding']['detail'] == encoding_dct
-        assert dct['encoding']['tooltip'] == encoding_dct
+    chart = alt.Chart(df).mark_point().encode(*args, **kwargs)
+    dct = chart.to_dict()
+    assert dct['encoding']['detail'] == encoding_dct
+    assert dct['encoding']['tooltip'] == encoding_dct
 
 
 def test_chart_operations():

pip install -e .[dev]
parse_log_pytest
requirements.txt
pytest
3.6
requirements.txt requirements_dev.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
alabaster==0.7.13
-e git+https://github.com/altair-viz/altair.git@d9e2d60c61945fc3bb0f59dbb962e320bdca9fda#egg=altair
attrs==22.2.0
Babel==2.11.0
backcall==0.2.0
certifi==2021.5.30
charset-normalizer==2.0.12
commonmark==0.9.1
decorator==5.1.1
docutils==0.17.1
entrypoints==0.4
flake8==5.0.4
idna==3.10
imagesize==1.4.1
importlib-metadata==4.2.0
iniconfig==1.1.1
ipython==7.16.3
ipython-genutils==0.2.0
jedi==0.17.2
Jinja2==3.0.3
jsonschema==3.2.0
m2r==0.3.1
MarkupSafe==2.0.1
mccabe==0.7.0
mistune==0.8.4
numpy==1.19.5
packaging==21.3
pandas==1.1.5
parso==0.7.1
pexpect==4.9.0
pickleshare==0.7.5
pluggy==1.0.0
prompt-toolkit==3.0.36
ptyprocess==0.7.0
py==1.11.0
pycodestyle==2.9.1
pyflakes==2.5.0
Pygments==2.14.0
pyparsing==3.1.4
pyrsistent==0.18.0
pytest==7.0.1
python-dateutil==2.9.0.post0
pytz==2025.2
recommonmark==0.7.1
requests==2.27.1
six==1.17.0
snowballstemmer==2.2.0
Sphinx==4.3.2
sphinxcontrib-applehelp==1.0.2
sphinxcontrib-devhelp==1.0.2
sphinxcontrib-htmlhelp==2.0.0
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.3
sphinxcontrib-serializinghtml==1.1.5
tomli==1.2.3
toolz==0.12.0
traitlets==4.3.3
typing_extensions==4.1.1
urllib3==1.26.20
vega-datasets==0.9.0
wcwidth==0.2.13
zipp==3.6.0

name: altair
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=21.2.2=py36h06a4308_0
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - alabaster==0.7.13
      - attrs==22.2.0
      - babel==2.11.0
      - backcall==0.2.0
      - charset-normalizer==2.0.12
      - commonmark==0.9.1
      - decorator==5.1.1
      - docutils==0.17.1
      - entrypoints==0.4
      - flake8==5.0.4
      - idna==3.10
      - imagesize==1.4.1
      - importlib-metadata==4.2.0
      - iniconfig==1.1.1
      - ipython==7.16.3
      - ipython-genutils==0.2.0
      - jedi==0.17.2
      - jinja2==3.0.3
      - jsonschema==3.2.0
      - m2r==0.3.1
      - markupsafe==2.0.1
      - mccabe==0.7.0
      - mistune==0.8.4
      - numpy==1.19.5
      - packaging==21.3
      - pandas==1.1.5
      - parso==0.7.1
      - pexpect==4.9.0
      - pickleshare==0.7.5
      - pluggy==1.0.0
      - prompt-toolkit==3.0.36
      - ptyprocess==0.7.0
      - py==1.11.0
      - pycodestyle==2.9.1
      - pyflakes==2.5.0
      - pygments==2.14.0
      - pyparsing==3.1.4
      - pyrsistent==0.18.0
      - pytest==7.0.1
      - python-dateutil==2.9.0.post0
      - pytz==2025.2
      - recommonmark==0.7.1
      - requests==2.27.1
      - six==1.17.0
      - snowballstemmer==2.2.0
      - sphinx==4.3.2
      - sphinxcontrib-applehelp==1.0.2
      - sphinxcontrib-devhelp==1.0.2
      - sphinxcontrib-htmlhelp==2.0.0
      - sphinxcontrib-jsmath==1.0.1
      - sphinxcontrib-qthelp==1.0.3
      - sphinxcontrib-serializinghtml==1.1.5
      - tomli==1.2.3
      - toolz==0.12.0
      - traitlets==4.3.3
      - typing-extensions==4.1.1
      - urllib3==1.26.20
      - vega-datasets==0.9.0
      - wcwidth==0.2.13
      - zipp==3.6.0
prefix: /opt/conda/envs/altair

altair/vegalite/v3/tests/test_api.py::test_multiple_encodings[args3-kwargs3]
altair/vegalite/v3/tests/test_api.py::test_chart_data_types altair/vegalite/v3/tests/test_api.py::test_chart_infer_types altair/vegalite/v3/tests/test_api.py::test_multiple_encodings[args0-kwargs0] altair/vegalite/v3/tests/test_api.py::test_multiple_encodings[args1-kwargs1] altair/vegalite/v3/tests/test_api.py::test_multiple_encodings[args2-kwargs2] altair/vegalite/v3/tests/test_api.py::test_multiple_encodings[args4-kwargs4] altair/vegalite/v3/tests/test_api.py::test_multiple_encodings[args5-kwargs5] altair/vegalite/v3/tests/test_api.py::test_chart_operations altair/vegalite/v3/tests/test_api.py::test_selection_to_dict altair/vegalite/v3/tests/test_api.py::test_facet altair/vegalite/v3/tests/test_api.py::test_facet_parse altair/vegalite/v3/tests/test_api.py::test_facet_parse_data altair/vegalite/v3/tests/test_api.py::test_selection altair/vegalite/v3/tests/test_api.py::test_transforms altair/vegalite/v3/tests/test_api.py::test_filter_transform_selection_predicates altair/vegalite/v3/tests/test_api.py::test_resolve_methods altair/vegalite/v3/tests/test_api.py::test_layer_marks altair/vegalite/v3/tests/test_api.py::test_layer_encodings altair/vegalite/v3/tests/test_api.py::test_add_selection altair/vegalite/v3/tests/test_api.py::test_selection_property altair/vegalite/v3/tests/test_api.py::test_LookupData altair/vegalite/v3/tests/test_api.py::test_themes altair/vegalite/v3/tests/test_api.py::test_chart_from_dict altair/vegalite/v3/tests/test_api.py::test_consolidate_datasets altair/vegalite/v3/tests/test_api.py::test_consolidate_InlineData altair/vegalite/v3/tests/test_api.py::test_deprecated_encodings altair/vegalite/v3/tests/test_api.py::test_repeat altair/vegalite/v3/tests/test_api.py::test_data_property altair/vegalite/v3/tests/test_api.py::test_subcharts_with_same_data[data.json-layer] altair/vegalite/v3/tests/test_api.py::test_subcharts_with_same_data[data.json-hconcat] altair/vegalite/v3/tests/test_api.py::test_subcharts_with_same_data[data.json-vconcat] altair/vegalite/v3/tests/test_api.py::test_subcharts_with_same_data[data.json-concat] altair/vegalite/v3/tests/test_api.py::test_subcharts_with_same_data[data1-layer] altair/vegalite/v3/tests/test_api.py::test_subcharts_with_same_data[data1-hconcat] altair/vegalite/v3/tests/test_api.py::test_subcharts_with_same_data[data1-vconcat] altair/vegalite/v3/tests/test_api.py::test_subcharts_with_same_data[data1-concat] altair/vegalite/v3/tests/test_api.py::test_subcharts_different_data[data.json-layer] altair/vegalite/v3/tests/test_api.py::test_subcharts_different_data[data.json-hconcat] altair/vegalite/v3/tests/test_api.py::test_subcharts_different_data[data.json-vconcat] altair/vegalite/v3/tests/test_api.py::test_subcharts_different_data[data.json-concat] altair/vegalite/v3/tests/test_api.py::test_subcharts_different_data[data1-layer] altair/vegalite/v3/tests/test_api.py::test_subcharts_different_data[data1-hconcat] altair/vegalite/v3/tests/test_api.py::test_subcharts_different_data[data1-vconcat] altair/vegalite/v3/tests/test_api.py::test_subcharts_different_data[data1-concat] altair/vegalite/v3/tests/test_api.py::test_layer_facet altair/vegalite/v3/tests/test_api.py::test_layer_errors
altair/vegalite/v2/schema/channels.py altair/vegalite/v3/schema/channels.py tools/generate_schema_wrapper.py
altair/vegalite/v2/schema/channels.py altair/vegalite/v3/schema/channels.py tools/generate_schema_wrapper.py